<?php
namespace Classes;

require_once dirname(dirname(__FILE__)).'/model/Attribut.php';
require_once 'Field.php';

use Model\Attribut;
use Classes\Field;

class Upload {
    public $files;
    public $target;
    public $max_size;
    public $max_width;
    public $max_height;
    public $min_width;
    public $min_height;
    public $new_width;
    public $ext;   
    public $type;    
    
    const FILES_INDEX = 'uploaded_files';
    
    const SUCCESS_CODE = 200; // Succès de l'upload du fichier
    const ERROR_CODE_SIZE = 201; // Erreur sur la taille du fichier
    const ERROR_CODE_DIMENSION = 202; // Erreur sur les dimensions du fichier
    const ERROR_CODE_TYPE = 203; // Erreur sur le type du fichier
    const ERROR_CODE_SERVER = 204; // Erreur sur le répertoire cible
    
    /**
     * Récupère les variables files et retraite les données dans un nouvean tableau
     * @param array $files : Variables files du formulaire
     * @return array $tabFiles
     */
    public function getFiles($files) {
        $tabFiles = array();
        foreach($files as $attr => $file) {
            foreach($file as $name => $value) {
                $tabFiles[$name][$attr] = $value;
            }
        }
        return $this->files = $tabFiles;
    }
    
    /**
     * Execute l'upload et le redimensionnement si on est en présence d'une image
     * @return array $codes
     */
    public function process() {
        $codes = array();
        $timestamp = mktime(date('H'), date('i'), date('s'), date('n'), date('j'), date('Y')); 
        
        // Récupération du répertoire racine
        $basedir = getcwd();
        
        // Parcourt tous les fichiers à uploader
        foreach($this->files as $alias => $file) {
            // Récupère le type du champ
            $type = $this->getType($alias);
            
            // Définit le type de l'upload
            $this->setType($type);  
            
            // Si aucun erreur s'est produit
            if($file['error'] == 0) {
                // Récupération de l'extension du fichier
                $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
                
                // Si l'extension est autorisée
                if(in_array(strtolower($extension), $this->ext)) {
                    // Si l'upload est de type image
                    if($type == 'image') { 
                        // Si la taille ne dépasse pas la taille limite
                        if(filesize($file['tmp_name']) <= ($this->max_size * pow(1024, 2))) {
                            // Récupération des infos sur le fichier
                            $fileInfos = getimagesize($file['tmp_name']);
                            
                            // Si la largeur et la hauteur ne dépasse pas les valeurs limites
                            if(($fileInfos[0] <= $this->max_width) && ($fileInfos[1] <= $this->max_height) && ($fileInfos[0] >= $this->min_width) && ($fileInfos[1] >= $this->min_height)) {
                                // Rennome le fichier
                                $newName = 'img'.$timestamp.'.'.$extension;
                                
                                // Si le répertoire existe
                                if(is_dir($basedir.$this->target)) {
                                    // Upload le fichier sur le serveur
                                    if(move_uploaded_file($file['tmp_name'], $basedir.$this->target.$newName)) {
                                        $this->resizeImage($newName, $fileInfos[0], $fileInfos[1], $extension);
                                        $codes[$alias]['code'] = Upload::SUCCESS_CODE;
                                        $codes[$alias]['file'] = $newName;
                                    } else {
                                        $codes[$alias]['code'] = Upload::ERROR_CODE_SERVER;
                                    }
                                } else {
                                    $codes[$alias]['code'] = Upload::ERROR_CODE_SERVER;
                                }
                            } else {
                                $codes[$alias]['code'] = Upload::ERROR_CODE_DIMENSION;
                            }
                        } else {
                            $codes[$alias]['code'] = Upload::ERROR_CODE_SIZE;
                        }
                    } elseif($type == 'file') {
                        // Si la taille ne dépasse pas la taille limite
                        if(filesize($file['tmp_name']) <= ($this->max_size * pow(1024, 2))) {
                            // Rennome le fichier
                            $newName = 'file'.$timestamp.'.'.$extension;
                            
                            // Si le répertoire existe
                            if(is_dir($basedir.$this->target)) {
                                // Upload le fichier sur le serveur
                                if(move_uploaded_file($file['tmp_name'], $basedir.$this->target.$newName)) {
                                    $codes[$alias]['code'] = Upload::SUCCESS_CODE;
                                    $codes[$alias]['file'] = $newName;
                                } else {
                                    $codes[$alias]['code'] = Upload::ERROR_CODE_SERVER;
                                }
                            } else {
                                $codes[$alias]['code'] = Upload::ERROR_CODE_SERVER;
                            }
                        } else {
                            $codes[$alias]['code'] = Upload::ERROR_CODE_SIZE;
                        }
                    }
                } else {
                    $codes[$alias]['code'] = Upload::ERROR_CODE_TYPE;
                }
            }
            $timestamp = mktime(date('H'), date('i'), date('s')+1, date('n'), date('j'), date('Y'));
        }        
        return $codes;
    }
    
    /**
     * Supprime le fichier demandé
     * @param string $filename : Nom du fichier à supprimer
     */
    public function deleteFile($filename) {
        require dirname(dirname(__FILE__)).'/config/config.php';
        $basedir = getcwd();
        $image = $basedir.$image['target'].$filename;
        $file = $basedir.$file['target'].$filename;
        if(file_exists($image)) {
            unlink($image);
        } elseif(file_exists($file)) {
            unlink($file);
        }
    }
    
    /**
     * Définit si l'upload est de type image ou de type fichier
     * @param string $type : Type de l'upload
     */
    private function setType($type='image') {
        require dirname(dirname(__FILE__)).'/config/config.php';
        if($type == 'image') {
            $this->target = $image['target'];
            $this->max_size = $image['max-size'];
            $this->max_width = $image['max-width'];
            $this->max_height = $image['max-height'];
            $this->min_width = $image['min-width'];
            $this->min_height = $image['min-height'];
            $this->new_width = $image['new-width'];
            $this->ext = $image['ext'];
            $this->type = $type;
        } elseif($type == 'file') {
            $this->target = $file['target'];
            $this->max_size = $file['max-size'];
            $this->max_width = null;
            $this->max_height = null;
            $this->min_width = null;
            $this->min_height = null;
            $this->new_width = null;
            $this->ext = $file['ext'];
            $this->type = $type;
        }
    }
    
    /**
     * Récupère le type du champ en question
     * @param string $alias : Alias du champ à uploader
     * @return string $type
     */
    private function getType($alias) {
        $attributObject = new Attribut();
        $type = $attributObject->getAttributByAlias($alias)->type;
        if($type == Field::IMAGE) {
            return $type = 'image';
        } elseif($type == Field::FILE) {
            return $type = 'file';
        }
    }
    
    /**
     * Redimensionne l'image uploadée
     * @param string $filename : Nom du fichier à redimensionner
     * @param int $width : Largeur de l'image à redimensionner
     * @param int $height : Hauteur de l'image à redimensionner
     * @param string $ext : Extension de l'image à redimensionner
     */
    private function resizeImage($filename, $width, $height, $ext) {
        require dirname(dirname(__FILE__)).'/config/config.php';
        $basedir = getcwd();
        $fullName = $basedir.$this->target.$filename;
        $ratio = ($this->new_width * 100)/$width;
        $newHeight = ($height * $ratio)/100;
        
        // Création d'une image à partir de la source
        switch($ext) {
            case 'jpg':
            case 'jpeg':
                $oldImage = imagecreatefromjpeg($fullName);
                break;
            case 'png':
                $oldImage = imagecreatefrompng($fullName);
                break;
            case 'gif':
                $oldImage = imagecreatefromgif($fullName);
        }
        
        // Création de l'image de la nouvelle image
        switch($ext) {
            case 'jpg':
            case 'jpeg':
                $newImage = imagecreatetruecolor($this->new_width, $newHeight);
                break;
            case 'png':
                $newImage = imagecreatetruecolor($this->new_width, $newHeight);
                imagesavealpha($newImage, true);
                $trans_color = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
                imagefill($newImage, 0, 0, $trans_color);
                break;
            case 'gif':
                $newImage = imagecreatetruecolor($this->new_width, $newHeight);
                break;
        }
        
        // Redimensionnement de l'image
        imagecopyresampled($newImage, $oldImage, 0, 0, 0, 0, $this->new_width, $newHeight, $width, $height);
        
        // Enregistrement de la nouvelle image
        switch ($ext) {
            case 'jpg':
            case 'jpeg':
                imagejpeg($newImage, $fullName);
                break;
            case 'png':
                imagepng($newImage, $fullName);
                break;
            case 'gif':
                imagegif($newImage, $fullName);
        }
        
        // Supprime les ressources images
        imagedestroy($oldImage);
        imagedestroy($newImage);
    }
}